package com.mg.plugin.cropgrow.calculator;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.mg.plugin.cropgrow.entity.CropGrowData;
import com.mg.plugin.cropgrow.entity.CropGrowDateData;
import com.mg.plugin.cropgrow.entity.StationData;
import com.mg.plugin.cropgrow.module.CropGrowDateModule;

@SuppressWarnings("unused")
public class CropGrowDateCalculator {

    public static List<CropGrowDateData> calcCropGrowDate(List<StationData> stationDataList, PlantType plantType) throws ParseException {
        List<CropGrowDateData> result = new ArrayList<CropGrowDateData>();
        SimpleDateFormat sdfTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat sdfDate = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat sdfDate1 = new SimpleDateFormat("MM/dd");
        List<CropGrowData> cropGrowData = CropGrowCalculator.calcCropGrow(stationDataList, plantType);
        for (CropGrowData data : cropGrowData) {
            double jmEt = data.getLeafFU();
            List<StationData> stationDatas = data.getStationDataList();
            double totalEt = 0;
            double leafAge = 0;
            double bAccTemp = 0.6 * data.getCropLeafCount() + 11.6;
            Date beginDate = sdfDate.parse(data.getPlantDay());
            //分蘖累积积温
            double fbT = 0;
            double qa = 0;
            int endLeafIndex = -1;
            double g = CropGrowProCalculator.calcLeafAge6(data.getRiceTrans());
            double accTem10 = 0;
            double maxGroutPro = 0;

            CropGrowDateData cropGrowDateData = new CropGrowDateData(data, sdfDate1.format(sdfDate.parse(data.getPlantDay())));
            for (StationData stationData : stationDatas) {
                Date calcDate = sdfTime.parse(stationData.getDate());
                if (beginDate.before(calcDate)) {
                    if (jmEt > totalEt && plantType == PlantType.A) {
                        double filmTempDiff = calcFilmTempDiff(stationData.getSunshine());
                        if (stationData.getAvgTemp()+filmTempDiff<=26.1D) {
                        	totalEt += calcET(stationData.getAvgTemp()+filmTempDiff);
        				} else {
        					totalEt += calcET(26.1D);
        				}
                    } else {
                        totalEt += stationData.getEffectTemp();
                    }

                    if (leafAge <= 4.8) {
                        leafAge = CropGrowProCalculator.calcLeafAge6(totalEt);
                        qa = totalEt;
                    } else if (leafAge < g + 1.5 && plantType == PlantType.A) {
                        leafAge = CropGrowProCalculator.calcLeafAge37(totalEt, qa, g);
                    } else {
                        leafAge = CropGrowProCalculator.calcLeafAge66(totalEt, g);
                    }
//                  leafAge = calcLeafAge6(totalEt);
                    if (leafAge > data.getCropLeafCount()) {
                        leafAge = data.getCropLeafCount();
                    }

                    stationData.setTotalEt(totalEt);
                    if (totalEt >= data.getEndLeaf() && endLeafIndex < 0) {
                        endLeafIndex = stationDatas.indexOf(stationData);
                    }

                    //分蘖当量，已确定
                    fbT += CropGrowProCalculator.calcTillerEt(stationData, data.getCropLeafCount(), leafAge);
                    if (totalEt >= data.getEarStage() && stationData.getAvgTemp() >= 10) {
                        //灌浆累积？？？？？？？？？？？
                        accTem10 += stationData.getAvgTemp() - 10;
                    }

                    //灌浆当量，已确定
                    double get = CropGrowProCalculator.calcGroutHot(accTem10, data.getGroutLength());
                    double groutPro = accTem10 > 0 ? CropGrowProCalculator.calcGroutPro(get) : 0;
                    maxGroutPro = maxGroutPro > groutPro ? maxGroutPro : groutPro;
                }

                assistEtToDate(fbT, data, totalEt, cropGrowDateData, stationData);
            }
            double kkl = calcKKL(stationDatas, endLeafIndex, data, bAccTemp);
            cropGrowDateData.setKKL(kkl);
            cropGrowDateData.setGroutPro(maxGroutPro);
            result.add(cropGrowDateData);
        }

        return result;
    }

    private static double calcKKL(List<StationData> stationDatas, int endLeafIndex, CropGrowData data, double bAccTemp) {
        double kkl = 0;
        for (int i = 1; i <= 20; i++) {
            StationData stationData = stationDatas.get(endLeafIndex + i - 8);
            //空壳率
            double obsGho = calcObsGho(stationData.getTotalEt(), data, stationData, bAccTemp);
            double obsGhoRatio = calcObsGhoRatio(i);
            kkl += obsGho * obsGhoRatio;
        }
        return kkl < 0 ? 0 : kkl;
    }

    private static void assistEtToDate(double fbt, CropGrowData data, double totalEt, CropGrowDateData cropGrowDateData, StationData stationData) throws ParseException {
        SimpleDateFormat sdfTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat sdfDate = new SimpleDateFormat("MM/dd");
        //分蘖高峰期
        double fbMax = 1.42875 * (3.41 * data.getCropLeafCount() - 23.6);
        //分蘖末期
        double fbEnd = 2.0 * (3.41 * data.getCropLeafCount() - 23.6);

        //OK
        if (totalEt >= data.getLeaf12() && cropGrowDateData.getLeaf12() == null) {
            cropGrowDateData.setLeaf12(sdfDate.format(sdfTime.parse(stationData.getDate())));
            return;
        }
        //OK
        if (totalEt >= data.getLeaf30() && cropGrowDateData.getLeaf30() == null) {
            cropGrowDateData.setLeaf30(sdfDate.format(sdfTime.parse(stationData.getDate())));
            return;
        }
        //OK
        if (totalEt >= data.getLeafFU() && cropGrowDateData.getLeafFU() == null) {
            cropGrowDateData.setLeafFU(sdfDate.format(sdfTime.parse(stationData.getDate())));
            return;
        }

        //OK
        if (totalEt >= data.getRiceTrans() && cropGrowDateData.getRiceTrans() == null) {
            cropGrowDateData.setRiceTrans(sdfDate.format(sdfTime.parse(stationData.getDate())));
            return;
        }

        //OK
        if (totalEt >= data.getTiller() && cropGrowDateData.getTiller() == null) {
            cropGrowDateData.setTiller(sdfDate.format(sdfTime.parse(stationData.getDate())));
            return;
        }
        //OK
        if (totalEt >= data.getLeaf37() && cropGrowDateData.getLeaf37() == null) {
            cropGrowDateData.setLeaf37(sdfDate.format(sdfTime.parse(stationData.getDate())));
            return;
        }
        //OK
        if (totalEt >= data.getLastLeaf() && cropGrowDateData.getLastLeaf() == null) {
            cropGrowDateData.setLastLeaf(sdfDate.format(sdfTime.parse(stationData.getDate())));
            return;
        }
        //OK
        if (totalEt >= data.getLeaf66() && cropGrowDateData.getLeaf66() == null) {
            cropGrowDateData.setLeaf66(sdfDate.format(sdfTime.parse(stationData.getDate())));
            return;
        }
        //OK
        if (fbt >= data.getValidTiller() && cropGrowDateData.getValidTiller() == null) {
            cropGrowDateData.setValidTiller(sdfDate.format(sdfTime.parse(stationData.getDate())));
            return;
        }
        //OK
        if (fbt >= fbMax && cropGrowDateData.getHighTiller() == null) {
            cropGrowDateData.setHighTiller(sdfDate.format(sdfTime.parse(stationData.getDate())));
            return;
        }
        //OK
        if (fbt >= fbEnd && cropGrowDateData.getEndTiller() == null) {
            cropGrowDateData.setEndTiller(sdfDate.format(sdfTime.parse(stationData.getDate())));
            return;
        }
        //OK
        if (totalEt >= data.getYoungEar() && cropGrowDateData.getYoungEar() == null) {
            cropGrowDateData.setYoungEar(sdfDate.format(sdfTime.parse(stationData.getDate())));
            return;
        }
        //OK
        if (totalEt >= data.getEndLeaf() && cropGrowDateData.getEndLeaf() == null) {
            cropGrowDateData.setEndLeaf(sdfDate.format(sdfTime.parse(stationData.getDate())));
            return;
        }
        //OK
        if (totalEt >= data.getEarStage() && cropGrowDateData.getEarStage() == null) {
            cropGrowDateData.setEarStage(sdfDate.format(sdfTime.parse(stationData.getDate())));
        }
    }

    //32
    public static double calcObsGhoRatio(int j) {
        if (j > 20 || j < 1) {
            return 0;
        }
//        double lJ1 = 20 * 0.4 + j * (20 - 40 * 0.4) / 20;
//        double lJ2 = 20 * 0.4 + (j - 1) * (20 - 40 * 0.4) / 20;
//        double e1 = -9.19024 * (10 * j / 20 - 10 * 0.4) / lJ1;
//        double e2 = -9.19024 * (10 * (j - 1) / 20 - 10 * 0.4) / lJ2;
//        double fj1 = 1 / (1 + Math.pow(Math.E, e1));
//        double fj2 = 1 / (1 + Math.pow(Math.E, e2));
//        return fj1 - fj2;


        switch (j) {
            case 1:
                return 0.09;
            case 2:
                return 0.016;
            case 3:
                return 0.028;
            case 4:
                return 0.046;
            case 5:
                return 0.067;
            case 6:
                return 0.093;
            case 7:
                return 0.112;
            case 8:
                return 0.12;
            case 9:
                return 0.115;
            case 10:
                return 0.098;
            case 11:
                return 0.078;
            case 12:
                return 0.06;
            case 13:
                return 0.044;
            case 14:
                return 0.031;
            case 15:
                return 0.021;
            case 16:
                return 0.014;
            case 17:
                return 0.01;
            case 18:
                return 0.006;
            case 19:
                return 0.002;
            case 20:
                return 0;
            default:
                return 0;
        }
    }

    /**
     * 公式9扣膜增温
     * @param sunshine
     * @return
     */
    private static double calcFilmTempDiff(double sunshine) {
        return 4.2 / (1 + Math.pow(Math.E, -9.19024 * (sunshine - 5.3) / 13.8)) + 1.4;
    }

	public static double calcObsGho(double totalEt, CropGrowData data, StationData stationData, double fitTemp) {
        if (totalEt < data.getYoungEar()) {
            return 0;
        }
        if (stationData.getAvgTemp() > fitTemp) {
            return 0;
        }
//        double tempDiff = stationData.getMaxTemp() - stationData.getMinTemp(); //9
//        double accTemp = (fitTemp - stationData.getMinTemp()) / tempDiff; //0.44
//        double vl = 14.2 - (53 * (Math.log(1.303947 / (accTemp + 0.102418) - 1))) / 9.19024; //12.3
//        double vh = 24 - vl;//11.7
//        double va = 7.519846 * Math.log(Math.pow(Math.E, -9.19024 * (vl - 14.2) / 53) + 1) + 1.201529 * vl - 19.13117;//2.2
//        double avl = accTemp * vl - va;//3.3
//        double v24 = 7.519846 * Math.log(Math.pow(Math.E, -9.19024 * (24 - 14.2) / 53) + 1) + 1.201529 * 24 - 19.13117;//10.97
//        double accFt = v24 - va - accTemp * vh; //3.57
//        double st = accFt * tempDiff;
//        if (Double.isNaN(st)) {
//            st = 40;
//        }
//        st = st > 40 ? 40 : st;
//        double res = 100 - 2.5 * st;
//        return res / 100;


        double tempDiff = stationData.getMaxTemp() - stationData.getMinTemp(); //9
        double accTemp = (fitTemp - stationData.getMinTemp()) / tempDiff; //0.44
        double vl = 14.2 - (53 * (Math.log(1.303947 / (accTemp + 0.102418) - 1))) / 9.19024; //12.3
        double vh = 24 - vl;//11.7
        double va = 7.519846 * Math.log(Math.pow(Math.E, -9.19024 * (vl - 14.2) / 53) + 1) + 1.201529 * vl - 19.13117;//2.2
        double avl = accTemp * vl - va;//3.3
        double v24 = 7.519846 * Math.log(Math.pow(Math.E, -9.19024 * (24 - 14.2) / 53) + 1) + 1.201529 * 24 - 19.13117;//10.97
        double accFt = v24 - va - accTemp * vh; //3.57
        double st = accFt * tempDiff;
        if (Double.isNaN(st)) {
            st = 40;
        }
        st = st > 40 ? 40 : st;
        double res = 100 - 100 / 40 * st;
        return res;
    }

    /**
     * 当量温度计算公式
     *
     * @param temp
     * @return
     */
    private static double calcET(double temp) {
        double power = 9.19024 * Math.pow((temp - 26.1) / 26.7, 2) - 4.59512 * 0.22;
        return 15.603 / (1 + Math.pow(Math.E, power));
    }
}
